package cn.itcast.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.itcast.service.ChatService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import reactor.core.publisher.Flux;

import java.util.UUID;

@Service
@Slf4j
@RequiredArgsConstructor
public class ChatServiceImpl implements ChatService {
    private final ChatClient chatClient;

    private final VectorStore vectorStore;

    @Override
    public String chat(String question, String sessionId) {
        log.info("带会话ID的聊天, question: {}, sessionId: {}", question, sessionId);
        //创建搜索请求，用于搜索相关文档
        var searchRequest = SearchRequest.builder()
                .query(question)//设置查询条件
                .topK(3)// 设置最多返回的文档数量
                .build();

        // 如果sessionId为空，生成一个新的
        String effectiveSessionId = StringUtils.hasText(sessionId) ? sessionId : UUID.randomUUID().toString();
        
        // 使用sessionId作为conversation标识，通过prompt()方法传递
        var content = this.chatClient.prompt(effectiveSessionId)
                .system(prompt -> prompt.param("now", DateUtil.now()))
                .advisors(advisor -> advisor
                        .advisors(new QuestionAnswerAdvisor(vectorStore, searchRequest))//设置RAG的Advisor
                        .param(AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY, sessionId))
                .user(question)
                .call()
                .content();
        log.info("question: {}, sessionId: {}, content: {}", question, effectiveSessionId, content);
        return content;
    }

    @Override
    public Flux<String> streamChat(String question) {
        log.info("开始流式聊天, question: {}", question);
        return this.chatClient.prompt()
                .user(question)
                .stream()
                .content();
    }

    @Override
    public Flux<String> chatStream(String question, String sessionId) {
        log.info("开始带会话ID的流式聊天, question: {}, sessionId: {}", question, sessionId);
        
        // 创建搜索请求，用于搜索相关文档
        var searchRequest = SearchRequest.builder()
                .query(question)
                .topK(3)
                .build();
        
        // 如果sessionId为空，生成一个新的
        String effectiveSessionId = StringUtils.hasText(sessionId) ? sessionId : UUID.randomUUID().toString();
        
        // 使用sessionId作为conversation标识，通过prompt()方法传递
        return this.chatClient.prompt(effectiveSessionId)
                .system(prompt -> prompt.param("now", DateUtil.now()))
                .advisors(advisor -> advisor
                        .advisors(new QuestionAnswerAdvisor(vectorStore, searchRequest)) // 设置RAG的Advisor
                        .param(AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY, effectiveSessionId))
                .user(question)
                .stream()
                .content()
                .concatWith(Flux.just("[END]")) // 添加[END]结束标识
                .doOnNext(content -> log.debug("流式响应片段: {}", content))
                .doOnComplete(() -> log.info("流式聊天完成, sessionId: {}", effectiveSessionId))
                .doOnError(error -> log.error("流式聊天错误, sessionId: " + effectiveSessionId, error));
    }

}
